import axios from 'axios'
import { showToast, showDialog, showLoadingToast, closeToast } from 'vant'
import { baseApi, isDev, baseUrl } from '@/utils/env'
import router from '@/router'
import { userApi } from '@/api/user'
//baseApi
// 请求计数器，用于跟踪当前活跃的请求数量
let requestCount = 0

// 显示全局 loading
const showLoading = () => {
    if (requestCount === 0) {
        showLoadingToast({
            message: '加载中...',
            forbidClick: true,
            duration: 0
        })
    }
    requestCount++
}

// 隐藏全局 loading
const hideLoading = () => {
    requestCount--
    if (requestCount === 0) {
        closeToast()
    }
}

// 用于存储获取 token 的 Promise，确保多个请求共用一个 Promise
let refreshTokenPromise = null

// 接口白名单配置
const whiteList = [
    '/user/request'  // 添加不需要显示403 toast的接口路径
]

// 重置 token Promise 的函数
const resetRefreshTokenPromise = () => {
    refreshTokenPromise = null
}

// 获取匿名 token 的函数
const getAnonymousToken = async () => {
    try {
        // 如果已经有一个获取 token 的请求在进行中，直接返回该 Promise
        if (refreshTokenPromise !== null) {
            return refreshTokenPromise
        }

        // 创建新的获取 token 的 Promise
        refreshTokenPromise = userApi.getAnonymousToken()
            .then(res => {
                if (res && res.data && res.data.access_token) {
                    // 保存新获取的 token
                    localStorage.setItem('token', res.data.access_token)
                    return res.data.access_token
                }
                throw new Error('获取匿名 token 失败')
            })
            .finally(() => {
                // 无论成功或失败，都重置 Promise，以便下次可以重新获取
                resetRefreshTokenPromise()
            })

        return refreshTokenPromise
    } catch (error) {
        resetRefreshTokenPromise()
        console.error('获取匿名 token 失败:', error)
        throw error
    }
}

const service = axios.create({
    baseURL: isDev ? baseApi : baseUrl,
    headers: {
        'Content-Type': 'application/json;charset=UTF-8'
    }
})

// 请求拦截器
service.interceptors.request.use(
    config => {
        // 显示全局 loading，除非配置中指定不显示
        if (!config.hideLoading) {
            showLoading()
        }

        // 获取token
        const token = localStorage.getItem('token')
        if (token) {
            config.headers['Authorization'] = 'Bearer ' + token
        }
        return config
    },
    error => {
        console.error('Request interceptor error:', error)
        // 请求错误时隐藏 loading
        hideLoading()
        return Promise.reject(error)
    }
)

// 响应拦截器
service.interceptors.response.use(
    response => {
        // 响应成功时隐藏 loading
        if (!response.config.hideLoading) {
            hideLoading()
        }

        const res = response.data
        // 如果是文件流，直接返回
        if (response.config.responseType === 'blob') {
            return response.data
        }
        if (res.code !== 0) {
            // 特定错误码处理
            if (response.code === 401) {
                showDialog({
                    title: '提示',
                    message: '登录已过期，请重新登录',
                }).then(() => {
                    router.push('/login')
                })
            }
            return Promise.reject(new Error(res.msg || '请求失败'))
        }
        return res
    },
    async error => {
        console.error('Response interceptor error:', error)
        // 响应错误时隐藏 loading
        hideLoading()

        const originalRequest = error.config

        // 检查是否是 401 错误（未授权），且请求未被标记为已经重试过
        if (error.response?.status === 401 || error.response?.data?.code === 401) {
            if (!originalRequest._retry) {
                originalRequest._retry = true

                try {
                    // 尝试获取匿名 token
                    const token = await getAnonymousToken()

                    // 更新原始请求的 Authorization 头
                    originalRequest.headers['Authorization'] = `Bearer ${token}`

                    // 重试原始请求
                    return service(originalRequest)
                } catch (refreshError) {
                    console.error('刷新 token 失败:', refreshError)
                    // 如果获取 token 失败，清除本地存储的 token
                    localStorage.removeItem('token')
                    // 可以选择重定向到登录页面或其他处理
                    return Promise.reject(refreshError)
                }
            }
        } else if (error.response?.data?.code === 403) {
            // 检查是否在白名单中
            const isInWhiteList = whiteList.some(path => originalRequest.url.includes(path))
            console.log('isInWhiteList', isInWhiteList)
            if (isInWhiteList) {
                showToast(error.response?.data?.msg || '请登录')
            } else {
                showToast(error.response?.data?.msg || '请登录')
                // 如果不在白名单，
                console.log('不在白名单，跳转登录', router)
                router.push('/login')
            }

        } else {
            showToast(error?.response?.data?.msg || error.msg || '请求失败')
        }

        return Promise.reject(error)
    }
)

// 封装请求方法
export const request = {
    get(url, params, config = {}) {
        return service.get(url, { params, ...config })
    },

    post(url, data, config = {}) {
        return service.post(url, data, config)
    },

    put(url, data, config = {}) {
        return service.put(url, data, config)
    },

    delete(url, data, config = {}) {
        return service.delete(url, { data, ...config })
    },

    // 文件上传
    upload(url, files, onProgress, config = {}) {
        const formData = new FormData()

        // 处理单个文件
        if (files instanceof File) {
            formData.append('file', files)
        }
        // 处理文件数组
        else if (Array.isArray(files)) {
            files.forEach((file, index) => {
                formData.append(`file${index}`, file)
            })
        }
        // 处理已经是 FormData 的情况
        else if (files instanceof FormData) {
            return service.post(url, files, {
                headers: {
                    'Content-Type': 'multipart/form-data'
                },
                onUploadProgress: progressEvent => {
                    if (onProgress) {
                        const progress = (progressEvent.loaded / progressEvent.total) * 100
                        onProgress(Math.round(progress))
                    }
                },
                ...config
            })
        }
        // 处理对象形式的文件数据
        else if (typeof files === 'object') {
            Object.keys(files).forEach(key => {
                if (files[key] instanceof File) {
                    formData.append(key, files[key])
                } else {
                    formData.append(key, JSON.stringify(files[key]))
                }
            })
        }

        return service.post(url, formData, {
            headers: {
                'Content-Type': 'multipart/form-data'
            },
            onUploadProgress: progressEvent => {
                if (onProgress) {
                    const progress = (progressEvent.loaded / progressEvent.total) * 100
                    onProgress(Math.round(progress))
                }
            },
            ...config
        })
    },

    // 文件下载
    download(url, params, fileName, config = {}) {
        return service({
            url,
            method: 'get',
            params,
            responseType: 'blob',
            ...config
        }).then(data => {
            if (!data || data.size === 0) {
                showToast('文件下载失败')
                return
            }

            // 处理文件名
            if (!fileName) {
                const disposition = response.headers['content-disposition']
                if (disposition) {
                    fileName = disposition.split('filename=')[1]
                }
            }

            // 下载文件
            const blob = new Blob([data])
            if (typeof window.navigator.msSaveBlob !== 'undefined') {
                // IE浏览器
                window.navigator.msSaveBlob(blob, fileName)
            } else {
                // 其他浏览器
                const link = document.createElement('a')
                link.href = window.URL.createObjectURL(blob)
                link.setAttribute('download', fileName)
                document.body.appendChild(link)
                link.click()
                document.body.removeChild(link)
                window.URL.revokeObjectURL(link.href)
            }
        })
    },

    // 图片预览
    previewImage(url, params, config = {}) {
        return service({
            url,
            method: 'get',
            params,
            responseType: 'blob',
            headers: {
                'Content-Type': 'blob'
            },
            ...config
        }).then(data => {
            return window.URL.createObjectURL(new Blob([data]))
        })
    }
}

// 开发环境下打印请求信息
if (isDev) {
    service.interceptors.request.use(
        config => {
            return config
        }
    )
    service.interceptors.response.use(
        response => {
            return response
        }
    )
}

export default request 